当我们对运行时资源进行缓存操作时,并没有一个统一标准来指明该资源是有效且可以被缓存的,在 Workbox 中,我们可以使用
workbox-cacheable-response模块,根据Response Status Code或Response Headers来决定是否对资源进行缓存操作。基于此,本章我们将讨论workbox-cacheable-response模块的使用。
# 基本使用
workbox.routing.registerRoute(
new RegExp('^https://third-party\\.example\\.com/images/'),
new workbox.strategies.CacheFirst({
cacheName: 'image-cache',
plugins: [
new workbox.cacheableResponse.Plugin({
statuses: [0, 200],
headers: {
'Is-Cacheable': 'true',
'X-Is-Cacheable': 'true'
}
})
]
})
);
上例中,我们通过在
workbox.strategies.CacheFirst的plugins属性中添加workbox.cacheableResponse.Plugin实例来设置指定路由可被缓存的条件,该路由的响应将在 Response Status Code 为 0 或 200,并且Response Headers中包含Is-Cacheable=true或X-Is-Cacheable=true时进行缓存处理。另外,亦可单独指定 statuses 或headers属性以达到只根据Response Status Code或Response Headers来判断资源是否可被缓存的目的。
workbox.cacheableResponse.Plugin的使用非常简单,由于它只能在workbox.strategies模块的CacheFirst、NetworkFirst及StaleWhileRevalidate中使用,因此我们可直接使用workbox.cacheableResponse.CacheableResponse在自定义的请求策略中完成资源是否可缓存的逻辑处理,比如:
const cacheable = new workbox.cacheableResponse.CacheableResponse({
statuses: [0, 200],
headers: {
'Is-Cacheable': 'true',
'X-Is-Cacheable': 'true'
}
});
const response = await fetch('/path/to/api');
if (cacheable.isResponseCacheable(response)) {
const cache = await caches.open('api-cache');
cache.put(response.url, response);
} else {
}
# 默认处理
在
workbox.strategies模块的CacheFirst、NetworkFirst及StaleWhileRevalidate中,如果我们未设置workbox.cacheableResponse.Plugin,那么它们将根据以下规则来对响应是否可缓存进行处理:
- 在
CacheFirst中,当Response Status Code为200时,则对响应进行缓存处理。 - 在
NetworkFirst、StaleWhileRevalidate中,当Response Status Code为0或200时,则对响应进行缓存处理。
上述设置中,CacheFirst 之所以不认可 Response Status Code 为 0 时的响应,主要是因为:
- 当
Response Status Code为 0 时,即表明该响应为不透明响应,我们无法获得此类响应的任何有效信息,这也意味着我们无法判断该响应是否包含错误信息; - 如果上述的不透明响应包含错误信息且
CacheFirst认可并缓存该响应,那么除非用户手动清除缓存或缓存过期后被清除,否则用户得到的永远是含有错误信息的响应; - 而在
NetworkFirst或StaleWhileRevalidate中,即使在某一刻缓存了含有错误信息的响应,它依旧可以在未来被正确的响应所替换。
# 不透明响应
上文我们提到了不透明响应,本小节将对其就行简单介绍。
不透明响应是 Fetch API 标准的一部分,表示在未启用 CORS 时远程服务器对请求的响应。对于此类响应,无论请求成功与否,该响应的 Response Status Code 始终为 0,且我们无法访问 Response 中的任何属性,或调用如 json、text 等构成 Body 的各种方法。它主要作用于以下标签来加载跨域资源:
<script><link rel="stylesheet"><img>、<video>和<audio><object>和<embed><iframe>
如果想要确定页面上的特定资源是否可以使用不透明响应,我们需要检查相关规范。比如,HTML 规范解释了不透明响应可作用于
<script>标签,但依旧有一些限制以防止错误信息泄漏。
- 由于不透明响应的 Response Status Code 始终为 0,且 Cache API 中的 add、addAll 方法不接受不在 2XX 范围内的 Response Status Code,因此我们应使用 put 方法来缓存不透明响应,比如:
const request = new Request('https://third-party-no-cors.com/', { mode: 'no-cors' });
fetch(request).then(response => cache.put(request, response));
为避免跨域信息的泄漏,浏览器在计算存储空间配额限制时会对不透明响应的大小进行填充(具体大小由浏览器决定,比如 Google Chrome 中每个不透明响应的存储空间最少为 7 MB),因此我们在对不透明响应进行缓存时,应时刻牢记这一点,因为根据响应的实际大小,可能很快就会突破存储空间的配额限制。
# 总结
本章我们首先对
workbox-cacheable-response的使用进行了简单介绍,然后讨论了workbox.strategies模块中CacheFirst、NetworkFirst及StaleWhileRevalidate对响应是否可缓存的默认处理,最后我们对不透明响应进行了讨论。下一章,我们将对Workbox` 缓存更新广播进行讨论。